package com

import (
	cr "crypto/rand"
	"encoding/base64"
	"encoding/binary"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"math/rand"
	"net"
	"net/url"
	"os"
	"os/user"
	"reflect"
	"strconv"
	"strings"
	"time"
)

/*
	@name 生成随机数
	num 数量
*/
func MakeRandomInt(num int) string {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))

	s := []string{}
	for i := 1; i <= num; i++ {

		x := r.Intn(10)
		t := fmt.Sprintf("%d", x)

		s = append(s, t)
	}
	return strings.Join(s, "")
}

// 创建GUID
func CreateGUID() string {
	b := make([]byte, 32)
	if _, err := io.ReadFull(cr.Reader, b); err != nil {
		return ""
	}

	return base64.URLEncoding.EncodeToString(b)
}
func MakeGUID() string {
	b := make([]byte, 32)
	if _, err := io.ReadFull(cr.Reader, b); err != nil {
		return ""
	}

	return string(b)
}

// 切割关键词为html片段
func TagSplit(keywords string) string {
	if "" == keywords {
		return ""
	}

	content := ""
	tags := strings.Split(keywords, ",")
	for _, value := range tags {
		content = content + fmt.Sprintf(`<a class="tags" href="/tag/%s/1">%s</a>,`, value, value)
	}
	return content
}

// json编码
func JsonEncode(data interface{}) (string, error) {
	a, err := json.Marshal(data)
	return string(a), err
}

// json解码
func JsonDecode(data string) (interface{}, error) {
	dataByte := []byte(data)
	var dat interface{}

	err := json.Unmarshal(dataByte, &dat)
	return dat, err
}

// 字符串追加至文件
func WriteAtFile(fullpath, str string) error {
	f, err := os.OpenFile(fullpath, os.O_WRONLY, 0644)
	if err == nil {
		// 查找文件末尾的偏移量
		n, _ := f.Seek(0, 2)
		// 从末尾的偏移量开始写入内容
		_, err = f.WriteAt([]byte(str), n)
	}
	defer f.Close()
	return err
}

// 字节追加至文件
func WriteByteAtFile(fullpath string, str []byte) error {
	f, err := os.OpenFile(fullpath, os.O_WRONLY, 0644)
	if err == nil {
		// 查找文件末尾的偏移量
		n, _ := f.Seek(0, 2)
		// 从末尾的偏移量开始写入内容
		_, err = f.WriteAt(str, n)
	}
	defer f.Close()
	return err
}

// 创建文件夹
func Mkdir(path string) error {
	return os.Mkdir(path, os.ModePerm)
}

// 创建多级目录
func MkdirAll(path string) error {
	return os.MkdirAll(path, os.ModePerm)
}

// 计算字符串长度
func StrLen(s string) int {
	sl := 0
	rs := []rune(s)
	for _, r := range rs {
		rint := int(r)
		if rint < 128 {
			sl++
		} else {
			sl += 2
		}
	}
	return sl
}

// 客户端ip

// 本地IP
func LocalIp() string {

	conn, err := net.Dial("udp", "google.com:80")
	if err != nil {
		fmt.Println(err.Error())
		return "127.0.0.1"
	}
	defer conn.Close()
	return strings.Split(conn.LocalAddr().String(), ":")[0]

}

// 本地mac
func LocalMac() string {
	// 获取本机的MAC地址
	interfaces, _ := net.Interfaces()
	mac := ""
	for _, inter := range interfaces {
		// fmt.Println(inter.Name)
		mac = mac + string(inter.HardwareAddr) // 获取本机MAC地址
	}
	return mac
}

// urlencode
func UrlEncode(urls string) string {
	return url.QueryEscape(urls)
}

// urldecode
func UrlDecode(urls string) string {
	escaped, _ := url.QueryUnescape(urls)
	return escaped
}

// 重复加密密码
func SecSha1(pwd string) string {
	return Sha1(Sha1(pwd))
}

// struct 转 map
func Struct2Map(obj interface{}) map[string]interface{} {
	t := reflect.TypeOf(obj)
	v := reflect.ValueOf(obj)

	var data = make(map[string]interface{})
	for i := 0; i < t.NumField(); i++ {
		data[t.Field(i).Name] = v.Field(i).Interface()
	}
	return data
}

/*
	获取本地外网IP
*/
func GetInternetIp() string {
	conn, err := net.Dial("udp", "baidu.com:80")
	if err != nil {
		return ""
	}
	defer conn.Close()
	return strings.Split(conn.LocalAddr().String(), ":")[0]
}

/*
	@name ip v4 转为int
*/
func Ip2long(ipstr string) uint32 {
	ip := net.ParseIP(ipstr)
	if ip == nil {
		return 0
	}
	ip = ip.To4()
	return binary.BigEndian.Uint32(ip)
}

/*
	@name int 转为 ip v4
*/
func Long2ip(ipLong uint32) string {
	ipByte := make([]byte, 4)
	binary.BigEndian.PutUint32(ipByte, ipLong)
	ip := net.IP(ipByte)
	return ip.String()
}

/*
	@name ipv4 16进制转10进制
*/
func Ipv4hexa2dec(addr string) (string, error) {
	decoded, err := hex.DecodeString(addr)
	if err != nil {
		return "", fmt.Errorf("decode error, %s", err)
	}
	ip := net.IP(ReverseByte(decoded))
	return ip.String(), nil
}

/*
	@name ipv6 16进制转字符串
*/
func Ipv6hexa2str(addr string) (string, error) {
	decoded, err := hex.DecodeString(addr)
	if err != nil {
		return "", fmt.Errorf("decode error, %s", err)
	}

	if len(decoded) != 16 {
		return "", fmt.Errorf("invalid IPv6 string")
	}

	buf := make([]byte, 0, 16)
	for i := 0; i < len(decoded); i += 4 {
		r := ReverseByte(decoded[i : i+4])
		buf = append(buf, r...)
	}

	ip := net.IP(buf)
	return ip.String(), nil
}

/**
@name ip 16进制端口转10进制
*/
func Port4hexa2dec(port string) (string, error) {
	port2int, err := strconv.ParseInt("0x"+port, 0, 64)
	if err != nil {
		return "", fmt.Errorf("invalid port, %s", port)
	}
	return fmt.Sprintf("%d", port2int), nil
}

// 反向反转字节数组
func ReverseByte(s []byte) []byte {
	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
		s[i], s[j] = s[j], s[i]
	}
	return s
}

// 判断动态值是否为空
func IsNil(i interface{}) bool {
	vi := reflect.ValueOf(i)
	if vi.Kind() == reflect.Ptr {
		return vi.IsNil()
	}
	return false
}

// 获取用户主目录
func GetUserHome() (string, error) {
	dir, err := user.Current()
	if nil == err {
		return dir.HomeDir, nil
	}
	return "", nil
}
